/*
 * Copyright TLR Team, Inc. All Rights Reserved.
 */
package com.tlr.device.service;

import com.tfb.service.utility.AppConst;
import static com.tfb.service.utility.AppConst.COUNTER;
import com.tfb.service.utility.HttpUtil;
import com.tfb.service.utility.JsonUtil;
import com.tfb.service.utility.Utils;
import com.tlr.device.model.Eban;
import com.tlr.device.model.EbanDay;
import com.tlr.device.model.EbanTime;
import static com.tlr.device.service.EbanDeviceAPI.getTimeFormat;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonNode;

public class EbanDevice10API extends EbanDeviceAPI {

    private static final Logger log = Logger.getLogger(EbanDevice10API.class);

    private String getDayInfoUrl(String token, String code, String date) throws UnsupportedEncodingException {
        return String.format(AppConst.EBAN_10_DAY_INFO, URLEncoder.encode("header[auth_ key]", JsonUtil.UTF8),
                             URLEncoder.encode("header[token]", JsonUtil.UTF8), token, code, date);
    }

    public String getDayInfoJsonString(String token, String code, String date) {
        try (CloseableHttpClient httpClient = HttpUtil.createHttpClient()) {
            String dayInfoUrl = this.getDayInfoUrl(token, code, date);
            log.info("Day info url: " + dayInfoUrl);
            try (CloseableHttpResponse dayInfoResp = httpClient.execute(new HttpGet(dayInfoUrl))) {
                String entityStr = EntityUtils.toString(dayInfoResp.getEntity(), JsonUtil.UTF8);
                // workaround
                if (entityStr.charAt(0) != '{') {
                    return entityStr.substring(1);
                }
                return entityStr;
            }
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            throw new RuntimeException(e);
        }
    }

    private void parseLocation(JsonNode data, Eban eban, String date) throws ParseException {
        if (!data.has("location")) {
            throw new RuntimeException("No location");
        }
        String locationStr = data.get("location").asText();
        String[] dotLocations = locationStr.split("#Dot");
        if (dotLocations == null || dotLocations.length == 0) {
            throw new RuntimeException("Location format is not correct");
        }
        String lastLocationStr = dotLocations[dotLocations.length - 1];
        if (lastLocationStr.contains("#line")) {
            String[] lineLocations = lastLocationStr.split("#line");
            if (lineLocations.length > 0) {
                lastLocationStr = lineLocations[lineLocations.length - 1];
            }
        }
        String[] locations = lastLocationStr.split("\\|");
        if (locations.length >= 7) {
            eban.setLng(locations[1].trim());
            eban.setLat(locations[2].trim());
            eban.setPosition(locations[3]);
            eban.setTime(parseTime(date, locations[6]));
        } else {
            throw new RuntimeException("Location format is not correct");
        }
    }

    private String parseTime(String date, String seconds) throws ParseException {
        SimpleDateFormat sf = EbanDeviceAPI.getDayFormat();
        SimpleDateFormat sf2 = getTimeFormat();
        Date dt = sf.parse(date);
        long locationTime = dt.getTime() + Long.parseLong(seconds) * 1000;
        return sf2.format(new Date(locationTime));
    }

    private void parsePoint(JsonNode data, Eban ban) {
        if (data.has("point_today")) {
            ban.setPoint(data.get("point_today").asText());
        } else {
            ban.setPoint("0");
        }
    }

    @Override
    public Eban getLastDeviceData(String token, String code, String date) {
        Eban eban = new Eban();
        try {
            eban = super.getLastDeviceData(token, code, date);
            if (eban.getLng() == null || eban.getLat() == null) {
                String lastData = getDayInfoJsonString(token, code, date);
                log.info("Last data: " + lastData);
                JsonNode data = JsonUtil.createJson(lastData);
                if (data.has("success") && data.get("success").getIntValue() == 1 && data.has("day_info")) {
                    data = data.get("day_info");
                    parseLocation(data, eban, date);
                    /*parsePoint(data, eban);
                    if (eban.getPoint().equals("0")) {
                        // Try to use old API to get point again
                        String point = getLastSDay(token, code, date);
                        JsonNode pointNode = JsonUtil.createJson(point);
                        if (pointNode.has("point")) {
                            eban.setPoint(pointNode.get("point").asText());
                        }
                    } //*/
                }
            }
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            eban.setEnabled(false);
            eban.setStatus_label("设备数据获取失败");
            eban.setStatus(0);
        }
        return eban;
    }

    @Override
    public EbanDay getDataByDayInfo(String token, String code, String date) throws Exception {
        try {
            SimpleDateFormat sf = EbanDeviceAPI.getDayFormat();
            SimpleDateFormat sf2 = getTimeFormat();
            Date dt = sf.parse(date);
            Calendar c = Calendar.getInstance();
            c.setTime(dt);
            c.add(Calendar.DAY_OF_MONTH, 1);
            date = sf.format(dt);
            int counter = COUNTER;
            EbanDay day = new EbanDay();
            do {
                String dataRest = getDataByDay(token, code, date);
                JsonNode dayRestJson = JsonUtil.createJson(dataRest);
                JsonNode dayRestDetail = dayRestJson.get("detail_rest");
                JsonNode messageNode = dayRestJson.get("message");
                dataRest = dayRestDetail != null ? dayRestDetail.asText() : null;
                day.setMessage(messageNode != null ? messageNode.asText().replaceAll("【", "#【") : "无数据");
                if (dataRest != null && !dataRest.isEmpty()) {
                    String[] timeSeg = dataRest.split(",");
                    for (String time : timeSeg) {
                        String[] segs = time.split("-");
                        EbanTime eTime = new EbanTime();
                        dt = sf.parse(date);
                        long start = dt.getTime() + Long.parseLong(segs[0]) * 1000;
                        long end = dt.getTime() + Long.parseLong(segs[1]) * 1000;
                        eTime.setStart(sf2.format(new Date(start)));
                        eTime.setEnd(sf2.format(new Date(end)));
                        eTime.setContent(segs[2]);
                        eTime.setAction(segs[3]);
                        day.getTimes().add(eTime);
                    }
                    day.setDate(date);
                    break;
                } else {
                    dt = sf.parse(date);
                    c = Calendar.getInstance();
                    c.setTime(dt);
                    c.add(Calendar.DAY_OF_MONTH, -1);
                    date = sf.format(c.getTime());
                }
            } while (--counter > 0);
            return day;
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            throw e;
        }
    }

}
